<?php
/**
 * 
 * Класс для работы с поисковым движком
 * @author Andrew
 *
 */
class Nimblecms_Search {
	
	/**
	 * 
	 * Путь к поисковому индексу
	 * @var string
	 */
	protected $_searchIndexPath = null;
	
	/**
	 * 
	 * Объект Zend_Search_Lucene
	 * @var Zend_Search_Lucene_Interface
	 */
	protected $_index = null;
	
	public function __construct($searchPath) {
		if(!$searchPath) {
			throw new Zend_Controller_Action_Exception('Path of search index not found', 500);
		}
		if($this->_searchIndexPath === null)
			$this->_searchIndexPath = $searchPath;
		set_time_limit(900);	
		if(!file_exists($this->_searchIndexPath) || !is_dir($this->_searchIndexPath)) {
			$this->_index = $this->createIndexPath();
		} elseif(file_exists($this->_searchIndexPath) && is_dir($this->_searchIndexPath)) {
			try {
				$this->_index = Zend_Search_Lucene::open($this->_searchIndexPath);
			} catch (Zend_Search_Lucene_Exception $e) {
				Nimblecms_Filesystem_Directory::rm_recursive($this->_searchIndexPath, true);
				$this->_index = $this->createIndexPath();
			}
		}
			
		Zend_Search_Lucene_Analysis_Analyzer::setDefault(new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8_CaseInsensitive());
	}
	
	/**
	 * 
	 * Заново создает и добавляет документы из модулей в поисковый индекс 
	 * @throws Zend_Controller_Action_Exception
	 * @return integer Количество добавленных документов в индекс
	 */
	public function updateIndex() {
		
		$this->_index = $this->createIndexPath();
		
		$modules = Nimblecms_Module_Loader::getInstance()->getModuleNames();
		
		$words = array();
		
		foreach ($modules as $module) {
        	$words_array = $this->_getSearchService($module);
        	
        	$words = array_merge($words, $words_array);
        }
		try {
        	$i = 0;
	        foreach ($words as $key=>$word) {
	        	foreach ($word['words'] as $lang=>$w) {
	        		foreach ($w as $k=>$v) {
	        			$doc = new Zend_Search_Lucene_Document();
	        			$doc->addField(Zend_Search_Lucene_Field::Keyword('word_id', $key . '_' . $lang . '_' . $v['id']));
	        			$doc->addField(Zend_Search_Lucene_Field::Keyword('uri', $v['uri']));
	        			$doc->addField(Zend_Search_Lucene_Field::Text('name', $v['name'], 'utf-8'));
	        			$doc->addField(Zend_Search_Lucene_Field::Text('content', $v['content'], 'utf-8'));
	        			$this->_index->addDocument($doc);
	        			$i++;
	        		}
	        	}
	        }
        } catch (Zend_Search_Lucene_Exception $e) {
        	throw new Zend_Controller_Action_Exception('Error index: ' . $e->getMessage(), 500);
        }
        
        $this->_index->optimize();
        
        return $i;
	}
	
	/**
	 * 
	 * Поиск в индексе
	 * @param string $query
	 */
	public function search($query) {
		Zend_Search_Lucene_Search_Query_Wildcard::setMinPrefixLength(0);
		
		$userQuery = new Zend_Search_Lucene_Search_Query_Phrase(explode(' ', trim(mb_strtolower($query, 'utf-8'))));
		
		$userQuery->setSlop(3);
		$hits = $this->_index->find($userQuery);
		$results = array(
			'hits' => $hits,
			'userQuery' => $userQuery
		);
		return $results;
	}
	
	/**
	 * 
	 * Создает поисковый индекс
	 * @throws Zend_Controller_Action_Exception
	 * @return Zend_Search_Lucene_Interface
	 */
	public function createIndexPath() {		
		try {
			$index = Zend_Search_Lucene::create($this->_searchIndexPath);
		} catch (Zend_Search_Lucene_Exception $e) {
			throw new Zend_Controller_Action_Exception('Error with create search index path: ' . $e->getMessage(), 500);
		}
		$this->_index = $index;
		return $index;
	}
	
	/**
	 * 
	 * Получает сервис поиска из модуля
	 * @param string $module название модуля
	 * @return array $words массив слов
	 */
	private function _getSearchService($module) {
		$dir = APPLICATION_PATH . DS . 'modules' . DS . $module . DS . 'service';
		
		if(!is_dir($dir)) {
			return array();
		}
		
		$file = $dir . DS . 'Search.php';
		
		if(!file_exists($file)) {
			return array();
		}
		
		$className = ucfirst($module) . '_Service_Search';
		
		$object = new $className();
		
		$words = $object->getwords();
		
		return $words;
	}
}